import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import type { CorePulumiApp } from "~/pulumi/apps/core/index.js";
import { getAwsAccountId, getAwsRegion } from "~/pulumi/apps/awsUtils.js";

export const configureS3BucketMalwareProtection = (app: CorePulumiApp) => {
    const awsAccountId = getAwsAccountId(app);
    const awsRegion = getAwsRegion(app);
    const eventBus = app.resources.eventBus;

    const bucket = app.resources.fileManagerBucket.output;

    const currentAccount = {
        StringEquals: {
            "aws:ResourceAccount": awsAccountId
        }
    };

    const managedByGuardDuty = {
        StringEquals: {
            "events:ManagedBy": "malware-protection-plan.guardduty.amazonaws.com"
        }
    };

    const assumeRole = aws.iam.getPolicyDocument({
        statements: [
            {
                effect: "Allow",
                principals: [
                    {
                        type: "Service",
                        identifiers: ["malware-protection-plan.guardduty.amazonaws.com"]
                    }
                ],
                actions: ["sts:AssumeRole"]
            }
        ]
    });

    const role = app.addResource(aws.iam.Role, {
        name: "fm-bucket-guardduty-role",
        config: {
            assumeRolePolicy: assumeRole.then(assumeRole => assumeRole.json)
        }
    });

    const policy = app.addResource(aws.iam.Policy, {
        name: `fm-bucket-guardduty-role-policy`,
        config: {
            description: "This policy enables GuardDuty to interact with the S3 bucket.",
            policy: {
                Version: "2012-10-17",
                Statement: [
                    {
                        Sid: "AllowManagedRuleToSendS3EventsToGuardDuty",
                        Effect: "Allow",
                        Action: ["events:PutRule"],
                        Resource: [
                            pulumi.interpolate`arn:aws:events:${awsRegion}:${awsAccountId}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`
                        ],
                        Condition: {
                            ...managedByGuardDuty,
                            "ForAllValues:StringEquals": {
                                "events:source": "aws.s3",
                                "events:detail-type": [
                                    "Object Created",
                                    "AWS API Call via CloudTrail"
                                ]
                            },
                            Null: {
                                "events:source": "false",
                                "events:detail-type": "false"
                            }
                        }
                    },
                    {
                        Sid: "AllowUpdateTargetAndDeleteManagedRule",
                        Effect: "Allow",
                        Action: ["events:DeleteRule", "events:PutTargets", "events:RemoveTargets"],
                        Resource: [
                            pulumi.interpolate`arn:aws:events:${awsRegion}:${awsAccountId}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`
                        ],
                        Condition: {
                            ...managedByGuardDuty
                        }
                    },
                    {
                        Sid: "AllowGuardDutyToMonitorEventBridgeManagedRule",
                        Effect: "Allow",
                        Action: ["events:DescribeRule", "events:ListTargetsByRule"],
                        Resource: [
                            pulumi.interpolate`arn:aws:events:${awsRegion}:${awsAccountId}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`
                        ]
                    },
                    {
                        Sid: "AllowPostScanTag",
                        Effect: "Allow",
                        Action: [
                            "s3:GetObjectTagging",
                            "s3:GetObjectVersionTagging",
                            "s3:PutObjectTagging",
                            "s3:PutObjectVersionTagging"
                        ],
                        Resource: [pulumi.interpolate`arn:aws:s3:::${bucket.bucket}/*`],
                        Condition: {
                            ...currentAccount
                        }
                    },
                    {
                        Sid: "AllowEnableS3EventBridgeEvents",
                        Effect: "Allow",
                        Action: ["s3:PutBucketNotification", "s3:GetBucketNotification"],
                        Resource: [pulumi.interpolate`arn:aws:s3:::${bucket.bucket}`],
                        Condition: {
                            ...currentAccount
                        }
                    },
                    {
                        Sid: "AllowPutValidationObject",
                        Effect: "Allow",
                        Action: ["s3:PutObject"],
                        Resource: [
                            pulumi.interpolate`arn:aws:s3:::${bucket.bucket}/malware-protection-resource-validation-object`
                        ],
                        Condition: {
                            ...currentAccount
                        }
                    },
                    {
                        Sid: "AllowCheckBucketOwnership",
                        Effect: "Allow",
                        Action: ["s3:ListBucket"],
                        Resource: [pulumi.interpolate`arn:aws:s3:::${bucket.bucket}`],
                        Condition: {
                            ...currentAccount
                        }
                    },
                    {
                        Sid: "AllowMalwareScan",
                        Effect: "Allow",
                        Action: ["s3:GetObject", "s3:GetObjectVersion"],
                        Resource: [pulumi.interpolate`arn:aws:s3:::${bucket.bucket}/*`],
                        Condition: {
                            ...currentAccount
                        }
                    }
                ]
            }
        }
    });

    app.addResource(aws.iam.RolePolicyAttachment, {
        name: `fm-bucket-malware-protection-role-policy-attachment`,
        config: {
            role: role.output.name,
            policyArn: policy.output.arn
        }
    });

    app.addResource(aws.guardduty.MalwareProtectionPlan, {
        name: `fm-bucket-malware-protection-plan`,
        config: {
            role: role.output.arn,
            protectedResource: {
                s3Bucket: {
                    bucketName: bucket.bucket
                }
            }
        }
    });

    // FORWARD EVENTS FROM "DEFAULT" TO CUSTOM EVENT BUS.

    // Create an IAM Role for EventBridge to forward events
    const eventBridgeRole = app.addResource(aws.iam.Role, {
        name: "guard-duty-forward-events-role",
        config: {
            assumeRolePolicy: JSON.stringify({
                Version: "2012-10-17",
                Statement: [
                    {
                        Effect: "Allow",
                        Principal: { Service: "events.amazonaws.com" },
                        Action: "sts:AssumeRole"
                    }
                ]
            })
        }
    });

    // Attach Policy to Allow EventBridge to PutEvents on Custom Event Bus
    app.addResource(aws.iam.RolePolicy, {
        name: "guard-duty-forward-events-policy",
        config: {
            role: eventBridgeRole.output,
            policy: pulumi.output(eventBus.output.arn).apply(arn =>
                JSON.stringify({
                    Version: "2012-10-17",
                    Statement: [
                        {
                            Effect: "Allow",
                            Action: "events:PutEvents",
                            Resource: arn
                        }
                    ]
                })
            )
        }
    });

    const forwardToCustomBusRule = app.addResource(aws.cloudwatch.EventRule, {
        name: "forward-events-from-default-to-custom-bus-rule",
        config: {
            eventBusName: "default",
            eventPattern: bucket.bucket.apply(name =>
                JSON.stringify({
                    source: ["aws.guardduty"],
                    "detail-type": ["GuardDuty Malware Protection Object Scan Result"],
                    detail: {
                        s3ObjectDetails: {
                            bucketName: [name]
                        }
                    }
                })
            )
        }
    });

    // Target: Send events to the custom event bus
    app.addResource(aws.cloudwatch.EventTarget, {
        name: "forward-events-from-default-to-custom-bus-target",
        config: {
            rule: forwardToCustomBusRule.output.name,
            roleArn: eventBridgeRole.output.arn,
            eventBusName: "default",
            arn: eventBus.output.arn
        }
    });
};
